package plgutils

import (
	"dgo/MyProj/PrjHttpClt"
	"dgo/MyProj/PrjHttpUtils"
	"dgo/goutils/utils"
	"dgo/plg/plgnet"
	"fmt"
	"gitee.com/ymofen/gobase"
	"gitee.com/ymofen/supervalue"
	"time"
)

type ObjStorageAdapter struct {
	PlgBase
	workers *utils.MultiGroupTask
	msglst  *utils.SyncCycleList
	url     string

	data_repl_raw string
	data_repl_map gobase.StrMap
}

/*
*

		{
	    "id": "proxystorage-adapter",
	    "type": "utils.objstorage.adapter",
	    "conf": {
	       "url":"http://127.0.0.1:6002/rpxs-proxy",
		   "data-repl":""
	    }
	  },
*/
func (this *ObjStorageAdapter) ReloadConf(conf *wrapper.SuperValue) error {
	if conf == nil {
		return nil
	}

	if this.workers == nil {

		this.workers = utils.NewMultiGroupTask()
		this.workers.ConfigWorkType(2)
		this.workers.ConfigMinWork(1).ConfigMaxWork(5).ConfigChannelMaxQueueSize(128)
		this.workers.Start()
		utils.Monitor.AddMonitor(this.workers.Monitor_push)
		utils.Monitor.AddMonitor(this.workers.Monitor_Pop)

	}

	{
		str := conf.StringByName("data-repl", "")
		if str != this.data_repl_raw {
			this.data_repl_raw = str
			if len(str) == 0 {
				this.data_repl_map = nil
			} else {
				this.data_repl_map = utils.NewStrMap(str, "\n")
			}
		}
	}

	if this.msglst == nil {
		this.msglst = utils.NewSyncCycleList()
	}
	strv := conf.StringByName("url", "")
	this.url = utils.ReplacePlaceholder(strv, "$$", "$$")
	_, this.url = utils.CheckTrimSuffix(this.url, "/")
	return nil
}

func (this *ObjStorageAdapter) Close() (err error) {
	this.workers.Stop()
	this.PlgBase.Close()

	return
}

func (this *ObjStorageAdapter) OnHttpStatus(rec *plgnet.PlgHttpRec) (rval interface{}, errcode int, err error) {
	itype := rec.QryAsInt("type", 0)
	if itype == 99 {
		json := wrapper.NewSVObject()
		json.SetKeyValue("url", this.url)
		json.SetKeyValue("workers", this.workers.StatusSimpleString())
		json.SetKeyValue("now", utils.NowString())

		if rec.QryAsInt("json", 0) == 1 {
			PrjHttpUtils.ResponseAsJSON(rec.RespW, json.AsJSONStringEx(false, true))
		} else {
			PrjHttpUtils.JSON2TableRec(rec.RespW, "", json.AsJSONString(false))
		}
	} else if itype == 98 {
		rec.ResponseSyncListNEx(this.msglst)
	} else if itype == 97 {
		rec.ResponseText(this.workers.StatusString())
	} else {
		var sb utils.BytesBuilder
		PrjHttpUtils.AppendIndexBody(&sb, "status", "status?type=99")
		PrjHttpUtils.AppendIndexBody(&sb, "msglist", "status?type=98&n=100&searchval=")
		PrjHttpUtils.AppendIndexBody(&sb, "worker-status", "status?type=97")
		PrjHttpUtils.ResponseBodyHtml(rec.RespW, sb.String())
	}
	return
}

func (this *ObjStorageAdapter) LogInfoMessage(s string, args ...interface{}) {
	this.msglst.LogMsg(s, args...)
	utils.Log.Msgf(this.PlugId, utils.LogLV_INFO, 1, s, args...)
}

func (this *ObjStorageAdapter) LogWarnMessage(s string, args ...interface{}) {
	this.msglst.LogMsg(s, args...)
	utils.Log.Msgf(this.PlugId, utils.LogLV_WARN, 1, s, args...)
}

/*
*
获取对象:

	{
	   "sessionid":"", "id":"", "match":"", "requestdata":""
	}

"code", 0, "id":"", "data":{}, "msg"
* 响应
errcode:

	101: 参数不完整
	102: 验证失败
*/
func (this *ObjStorageAdapter) GetValue(itype int, args ...interface{}) (rval interface{}) {
	if itype == 1 {
		if len(args) < 1 {
			return nil
		}
		var json = args[0].(*wrapper.SuperValue)
		rval = json
		sessionid := json.StringByName("sessionid", "")
		if len(sessionid) == 0 {
			return fmt.Errorf("缺少sessionid参数")
		}
		datastr := json.AsJSONString(false)
		url := fmt.Sprintf("%s/get", this.url)
		ok, e0 := this.workers.PostTaskFuncAndWait(sessionid, time.Second*10, func() {
			resp, err := PrjHttpClt.PostJsonEx2(url, datastr)
			if err != nil {
				rval = err
			} else {
				defer resp.Clear()
				if resp.Int8ByName("code", 0) == -1 {
					errcode := resp.IntByName("errcode", 0)
					if errcode > 0 {
						rval = fmt.Errorf("%d:%s", errcode, resp.StringByName("msg", "未知的认证错误消息"))
					} else {
						rval = fmt.Errorf("%s", resp.StringByName("msg", "未知的认证错误消息"))
					}
				} else {
					objectid := resp.StringByName("id", "")
					json.SetKeyValue("id", objectid)
					repl := this.data_repl_map
					if repl != nil && len(repl) > 0 {
						datastr := resp.StringByName("data", "")
						datastr1 := repl.ExecReplace(datastr)
						data, err := wrapper.NewSVFromBuf([]byte(datastr1))
						if err != nil {
							this.LogWarnMessage("[%s]替换后解析异常:%s, resp:%s", objectid, err.Error(), resp.String())
							json.SetKeyValue("data", resp.ValueByName("data"))
						} else {
							json.SetKeyValue("data", data)
						}
					} else {
						json.SetKeyValue("data", resp.ValueByName("data"))
					}
				}
			}
		})

		if e0 != nil {
			return e0
		}

		if !ok {
			return fmt.Errorf("排队执行超时")
		}

		return rval
	}
	return nil
}

/*
*

	action
	  ping(1):  {"sessionid":"", "id":"XXX", "data":{}}
	  release(2): {"sessionid":"", "id":"XXX", "data":{}, "reason":""}
*/
func (this *ObjStorageAdapter) OperaAction(action int, args ...interface{}) (rval error) {
	if action == 1 {
		if len(args) < 1 {
			return fmt.Errorf("非法的传入参数")
		}
		argsMap := args[0].(*wrapper.SuperValue)
		sessionid := argsMap.StringByName("sessionid", "")
		id := argsMap.StringByName("id", "")
		if sessionid == "" {
			return fmt.Errorf("参数异常:SessionID为空")
		}
		if id == "" {
			return fmt.Errorf("参数异常:对象ID为空")
		}
		url := fmt.Sprintf("%s/ping", this.url)
		datastr := argsMap.AsJSONString(false)

		ok, err := this.workers.PostTaskFuncAndWait(sessionid, time.Second*10, func() {
			resp, err := PrjHttpClt.PostJsonEx2(url, datastr)
			if err != nil {
				this.LogWarnMessage("执行PING异常:%s, data:%s, url:%s", err.Error(), datastr, url)
				rval = err
				return
			} else {
				defer resp.Clear()
				argsMap.CopyFrom(resp)
			}
			return
		})
		if err != nil { // 非法
			return err
		}
		if !ok {
			return fmt.Errorf("排队执行超时")
		}

		//
		//ok, err := this.workers.PostTaskFuncAndWait(sessionid, time.Second*10, func() {
		//	resp, err := PrjHttpClt.PostJsonEx2(url, datastr)
		//	if err != nil {
		//		this.LogWarnMessage("执行PING异常:%s, data:%s, url:%s", err.Error(), datastr, url)
		//		return
		//	} else {
		//		defer resp.Clear()
		//		argsMap.CopyFrom(resp)
		//		if resp.Int8ByName("code", 0) == -1 {
		//			errcode := resp.IntByName("errcode", 0)
		//			if errcode == 102 {
		//				rval = fmt.Errorf("%s", resp.StringByName("msg", "对象异常"))
		//			} else {
		//				this.LogWarnMessage("执行PING异常:%s, data:%s, url:%s", resp.StringByName("msg", "未知错误"), datastr, url)
		//			}
		//		}
		//	}
		//	return
		//})
		//if err != nil {
		//	return nil
		//}
		//if !ok {
		//	return nil
		//}

		return rval
	} else if action == 2 {
		if len(args) < 1 {
			return fmt.Errorf("非法的传入参数")
		}
		json := args[0].(*wrapper.SuperValue)
		sessionid := json.StringByName("sessionid", "")
		id := json.StringByName("id", "")
		if sessionid == "" {
			return fmt.Errorf("sessionid为空")
		}
		if id == "" {
			return fmt.Errorf("对象ID为空")
		}
		url := fmt.Sprintf("%s/release", this.url)
		datastr := json.AsJSONString(false)

		this.workers.PostTaskFuncAndWait(sessionid, time.Second*10, func() {
			resp, err := PrjHttpClt.PostJsonEx2(url, datastr)
			if err != nil {
				this.LogWarnMessage("执行release异常:%s, data:%s, url:%s", err.Error(), datastr, url)
				return
			} else {
				defer resp.Clear()
				if resp.Int8ByName("code", 0) == -1 {
					this.LogWarnMessage("执行release异常:%s, data:%s, url:%s", resp.StringByName("msg", "未知错误"), datastr, url)
				}
			}
			return
		})
		return nil
	}
	return nil

}

func CreateObjStorageAdapterPlgFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &ObjStorageAdapter{}

	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.PlugId = str
		}
	}
	rval = obj
	return
}
